package BusinessLogic;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.InvalidParameterException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import BusinessLogic.Result.ResultType;
import DatabasePackage.DatabaseManager;

/**
 * 		   ActionManager is the abstract base class for all
 *         ActionManagers. An action manager is used in the system in order to
 *         perform actions received from the view component and dispatched via
 *         the RequestHandler. The main functionality implemented in
 *         ActionManager is common data/methods used by all action managers.
 */
public abstract class ActionManager {
  // Action annotation- annotates an action method
  @Retention(RetentionPolicy.RUNTIME) public @interface Action {
  }
  public static final String ActionKey = "action";
  protected DatabaseManager dbMng;
  // Constant values for parameter keys
  // All action managers need to hold a user manager in order to check
  // action validity according to a given user.

  
  public ActionManager(DatabaseManager dbMng) {
    this.dbMng = dbMng;
  }
  
  /**
   * Makes sure the parameter map includes all of the required parameter keys.
   * 
   * @param params
   *          the parameters received
   * @param requiredParams
   *          the required parameters
   */
  protected static void validateParams(Map<String, String[]> params, List<String> requiredParams) {
    for (String param : requiredParams)
      if (!params.containsKey(param))
        throw new InvalidParameterException("Missing parameter " + param + " in parameters list.");
  }
  
  /**
   * Gets a string value from the parameters at the given key
   * 
   * @param params
   *          the parameters
   * @param key
   *          the wanted key
   * @return the string value of the parameter
   */
  protected String getStringParam(Map<String, String[]> params, String key) {
    return params.get(key)[0];
  }
  
  /**
   * Gets a UUID value from the parameters at the given key
   * 
   * @param params
   *          the parameters
   * @param key
   *          the wanted key
   * @return the UUID value of the parameter
   * @throws IllegalArgumentException
   *           exception thrown if parameter can't be parsed as a UUID
   */
  protected UUID getUUIDParam(Map<String, String[]> params, String key) throws IllegalArgumentException {
    return UUID.fromString(params.get(key)[0]);
  }
  
  /**
   * Gets a boolean value from the parameters at the given key. This is used to
   * translate data received from a view checkbox.. If the parameter exists in
   * the parameters and its value is "on" the returned boolean should be true.
   * Otherwise, it will return false.
   * 
   * @param params
   *          the parameters
   * @param key
   *          the wanted key
   * @return the boolean value of the parameter
   */
  protected boolean getBooleanParam(Map<String, String[]> params, String key) {
    String[] isDonorStr = params.get(key);
    return isDonorStr != null && isDonorStr[0].equals("on");
  }
  
  /**
   * Gets a int value from the parameters at the given key
   * 
   * @param params
   *          the parameters
   * @param key
   *          the wanted key
   * @return the int value of the parameter
   * @throws NumberFormatException
   *           - if the string does not contain a parsable integer
   */
  protected int getIntParam(Map<String, String[]> params, String key) throws NumberFormatException {
    return Integer.parseInt(params.get(key)[0]);
  }
  
  protected float getFloatParam(Map<String, String[]> params, String key) throws NumberFormatException {
    return Float.parseFloat(params.get(key)[0]);
  }
  
  /**
   * Creates a success Result object with the given return value
   * 
   * @param successReturnValue
   *          the wanted return value
   * @return the new success Result object
   */
  public static Result createSuccessResult(Object successReturnValue) {
    return new Result(ResultType.SUCCESS, successReturnValue);
  }
  
  protected void safeCloseConnection(Connection con){
		try {
      if (con!=null && !con.isClosed())
      	  con.close();
    } catch (SQLException e) {
      System.err.append("Failed to close the connection");
    }
	}
  /**
   * Creates a failure Result object with the given error message
   * 
   * @param failureMessage
   *          the wanted failure message
   * @return the new failure Result object
   */
  public static Result createFailureResult(String failureMessage) {
    return new Result(ResultType.FAILURE, failureMessage);
  }
  public static Result createFailureResult(Object returnValue) {
	    return new Result(ResultType.FAILURE, returnValue);
	  }
}
